/**
 * @func 手写 Promise
 * @param {function} executor 
 */
// 声明构造函数
function Promise(executor){
    // 添加属性
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    this.callbacks=[];
    // 保存实例对象的 this 值
    const self = this;
    // resolve 函数
    function resolve(data){
        // 判断状态  状态只能修改一次
        if(self.PromiseState!=='pending') return;
        // 1. 修改对象状态 
        self.PromiseState = 'fulfilled';
        // 2. 设置对象结果值
        self.PromiseResult = data;
        // 异步执行
        setTimeout(() => {
            // 调用成功的回调函数
            self.callbacks.forEach(item =>{
                item.onResolved(data);
            });
        }) 
    }
    // ewject 函数
    function reject(data){
        // 判断状态
        if(self.PromiseState!=='pending') return;
        // 1. 修改对象状态 
        self.PromiseState = 'rejected';
        // 2. 设置对象结果值
        self.PromiseResult = data;
        setTimeout(() => {
            // 调用失败的回调函数
            self.callbacks.forEach(item =>{
                item.onRejected(data);
            });
        })
    }

    try{
        // 同步调用 [执行器函数]
        executor(resolve,reject);
    }catch(e) {
        reject(e);
    }
}

// 添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){
    const self = this;
    // 判断回调函数参数 不传参数=默认参数
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
    }
    return new Promise((resolve,reject) =>{
        // 封装函数
        const self=this;
        function callback(type){
            try{
                let result=type(self.PromiseResult);
                 if(result instanceof Promise){
                     result.then(v=>{
                         resolve(v);
                     },r=>{
                         reject(r);
                     })
                 } else {
                     resolve(result);
                 }
             }catch(e){
                 reject(e);
             } 
        }
         // 调用回调函数
        if(this.PromiseState==='fulfilled'){
            // 异步执行
            setTimeout(()=>{
                 callback(onResolved);
            })
        }
        if(this.PromiseState==='rejected'){
           // 异步执行
            setTimeout(()=>{
               callback(onRejected);
           })
        }
        if(this.PromiseState==='pending'){
            // 保存回调函数
            this.callbacks.push( {
                onResolved:function(){
                   callback(onResolved);
                },
                onRejected:function(){
                   callback(onRejected);
                }
            })
        }
    })
}

// 添加 catch 方法
Promise.prototype.catch = function(onRejected){
    return this.then(undefined,onRejected);
}

// 添加 resolve 方法
// 它是属于Promise函数对象的，不是属于实例对象的
Promise.resolve = function(value) {
    // 返回 Promise 对象
    return new Promise((resolve,reject) =>{
        if(value instanceof Promise){
            value.then(v=>{
                resolve(v);
            },r=>{
                reject(r);
            })
        } else {
            // 状态设置为成功
            resolve(value);
        }
    })
}

// 添加 reject 方法
Promise.reject = function(reason) {
    return new Promise((resolve,reject) => {
        reject(reason);
    })
}

// 添加 all 方法
Promise.all = function(promises){
    // 返回结果为 Promise 对象
    return new Promise((resolve,reject) =>{
        // 声明变量
        let count = 0;
        let arr = [];
        // 遍历
        for(let i=0;i<promises.length;i++){
            // 用then,保证异步任务顺序也能一致
            promises[i].then(v => {
                // 得到对象的状态是成功
                // 每个 promise 对象都成功
                count++;
                // 将当前 promise 对象成功的结果 存入到数组中
                // push 不能保证顺序
                arr[i] =v;
                if(count === promises.length){
                    resolve(arr)
                }
            },r => {
                reject(r);
            });
        }
    });
}

Promise.race = function(promises) {
    return new Promise((resolve,reject) => {
        for(let i=0;i<promises.length;i++) {
            // 使用 then，谁先改变状态，谁就决定结果
            promises[i].then(v => {
                // 修改返回对象的状态 [成功]
                resolve(v);
            },r =>{
                // 修改返回对象的状态 [失败]
                reject(r);
            })
        }
    })
}